<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
 * PHP version 5
 *
 * This source file is subject to version 2.1 of the GNU Lesser General Public
 * License, that is bundled with this package in the file COPYING, available
 * through the world wide web at the following URI:
 * http://www.gnu.org/copyleft/lesser.html.
 *
 * @package    ZNF
 * @subpackage Config
 * @author     Alessandro Rossini <http://www.alessandrorossini.org>
 * @author     Graziano Liberati <http://www.liberati.org>
 * @copyright  2004-2007 The ZNF Development Team
 * @license    LGPL License 2.1 <http://www.gnu.org/copyleft/lesser.html>
 * @version    SVN $Id: DBConfig.php 43 2007-06-26 23:36:35Z aronnax $
 * @since      Release 0.7.5
 * @link       http://www.zeronotice.org
 */

/**
 * <i>ZNF_Config_DBConfig</i> contains the collection of static database configuration informations.
 *
 * Returns the <i>ZNF_Config_DBConfig</i> object reference with a singleton
 * pattern.
 *
 * @access     public
 * @package    ZNF
 * @subpackage Config
 * @author     Alessandro Rossini <http://www.alessandrorossini.org>
 * @author     Graziano Liberati <http://www.liberati.org>
 * @copyright  2004-2007 The ZNF Development Team
 * @license    LGPL License 2.1 <http://www.gnu.org/copyleft/lesser.html>
 * @version    SVN $Id: DBConfig.php 43 2007-06-26 23:36:35Z aronnax $
 * @since      Release 0.7.5
 * @link       http://www.zeronotice.org
 */
class ZNF_Config_DBConfig
{

    /**
     * Name of the configuration file.
     */
    const CONFIG_FILE = 'znf-db-config.xml';

    /**
     * The <i>ZNF_Config_DBConfig</i> object reference.
     *
     * @access protected
     * @staticvar ZNF_Config_DBConfig $_dbConfig
     */
    static protected $_dbConfig;

    /**
     * The array of the configuration file.
     *
     * @access protected
     * @var array $_config
     */
    protected $_config;

    /**
     * Private constructor to avoid <i>ZNF_Config_DBConfig</i> object creation.
     *
     * @access private
     */
    private function __construct()
    {
        $this->_parseConfiguration();
    }

    /**
     * Private clonator to avoid <i>ZNF_Config_DBConfig</i> object clonation.
     *
     * @access private
     */
    private function __clone()
    {
    }

    /**
     * Returns the reference to the <i>ZNF_Config_DBConfig</i> object with a singleton pattern.
     *
     * This object is shared by all the classes that require the database
     * configuration.
     *
     * @static
     * @access public
     * @return ZNF_Config_DBConfig
     */
    static public function getInstance()
    {
        if (!(isset(self::$_dbConfig))) {
            self::$_dbConfig = new ZNF_Config_DBConfig();
        }

        return self::$_dbConfig;
    }

    /**
     * Parses and validates the configuration file.
     *
     * For performance reasons implements a caching mechanism that serializes the
     * configuration file in an internal structure.
     *
     * @access protected
     */
    protected function _parseConfiguration()
    {
        $xmlTimestamp = filemtime(ZNF::CONFIG_DIR . '/' . self::CONFIG_FILE);
        $serializedTimestamp = @filemtime(ZNF::CACHE_DIR . '/' . self::CONFIG_FILE . '.cache');

        if ($xmlTimestamp <= $serializedTimestamp) {
            $this->_config = unserialize(file_get_contents(ZNF::CACHE_DIR . '/' . self::CONFIG_FILE . '.cache'));
        } else {
            $configXml = new DOMDocument('1.0','utf-8');
            $configXml->load(ZNF::CONFIG_DIR . '/' . self::CONFIG_FILE);

            // quick hack to make ZNF work as a PEAR package, to be improved
            $dirName = dirname(__FILE__);
            $schemaPath = substr($dirName, 0, strpos($dirName, 'Config')) . "xsd/znf-db-config.xsd";
            if (!$configXml->schemaValidate($schemaPath)) {
                $translation = new ZNF_Presentation_Translation('ZNF', $_SESSION['znf']['lang']);
                throw new ZNF_Config_DBConfigException($translation->get('errorDbCfgFileNotValid'));
            }

            $xpath = new DOMXPath($configXml);
            $xpath->registerNamespace('db', 'http://www.zeronotice.org/ZNF/znf-db-config');
            $config = array();
            $default = $xpath->query('/db:znf-db-config/db:db[@default="true"]');

            if ($default->length == 1) {
                $config['db']['dbms']     = $default->item(0)->getAttribute('dbms');
                $config['db']['username'] = $default->item(0)->getAttribute('username');
                $config['db']['password'] = $default->item(0)->getAttribute('password');
                $config['db']['hostname'] = $default->item(0)->getAttribute('hostname');
                $config['db']['dbname']   = $default->item(0)->getAttribute('dbname');
                $config['db']['tableprefix']   = $default->item(0)->getAttribute('tableprefix');
            // check if only one default action is specified
            } elseif ($default->length > 1) {
                $translation = new ZNF_Presentation_Translation('ZNF', $_SESSION['znf']['lang']);
                throw new ZNF_Config_DBConfigException($translation->get('errorDbCfgOneDbDefault'));
            // check if at least one default action is specified
            } else {
                $translation = new ZNF_Presentation_Translation('ZNF', $_SESSION['znf']['lang']);
                throw new ZNF_Config_DBConfigException($translation->get('errorDbCfgAtLeastOneDbDefault'));
            }

            file_put_contents(ZNF::CACHE_DIR . '/' . self::CONFIG_FILE . '.cache', serialize($config));
            $this->_config = $config;
        }
    }

    /**
     * Returns the database DBMS.
     *
     * @access public
     * @return string
     */
    public function getDbms()
    {
        return $this->_config['db']['dbms'];
    }

    /**
     * Returns the database username.
     *
     * @access public
     * @return string
     */
    public function getUsername()
    {
        return $this->_config['db']['username'];
    }

    /**
     * Returns the database password.
     *
     * @access public
     * @return string
     */
    public function getPassword()
    {
        return $this->_config['db']['password'];
    }

    /**
     * Returns the database hostname.
     *
     * @access public
     * @return string
     */
    public function getHostname()
    {
        return $this->_config['db']['hostname'];
    }

    /**
     * Returns the database dbname.
     *
     * @access public
     * @return string
     */
    public function getDbname()
    {
        return $this->_config['db']['dbname'];
    }

    /**
     * Returns the database table prefix.
     *
     * @access public
     * @return string
     */
    public function getTablePrefix()
    {
        return $this->_config['db']['tableprefix'];
    }

    /**
     * Destroys the <i>ZNF_Config_DBConfig</i> object.
     *
     * @access public
     */
    public function __destruct()
    {
    }

}

/**
 * <i>ZNF_Config_DBConfigException</i> is the exception type for the <i>ZNF_Config_DBConfig</i> class.
 *
 * <i>ZNF_Config_DBConfigException</i> extends the <i>Exception</i> class of PHP5.
 *
 * @access     public
 * @package    ZNF
 * @subpackage Config
 * @author     Alessandro Rossini <http://www.alessandrorossini.org>
 * @author     Graziano Liberati <http://www.liberati.org>
 * @copyright  2004-2007 The ZNF Development Team
 * @license    LGPL License 2.1 <http://www.gnu.org/copyleft/lesser.html>
 * @version    SVN $Id: DBConfig.php 43 2007-06-26 23:36:35Z aronnax $
 * @since      Release 0.7.5
 * @link       http://www.zeronotice.org
 */
class ZNF_Config_DBConfigException extends Exception
{
}

?>
